package com.yunfei.utils;

import java.util.Scanner;

public class DESEncrypt
{
    private static final String key = "ONWF2YIEV34ISBL";
    private static final int[] KnL = new int[32];
    private static final int[] KnR = new int[32];
    private static final int[] Kn3 = new int[32];

    private static void make2key(char[] aptr, char[] kptr)
    {
        int[] savek = new int[64];

        cpDkey(savek);
        des2key(Df_Key, true);
        for (int i = 0; i < 16; i++) {
            kptr[i] = Df_Key[i];
        }
        boolean first = true;
        int ct = 0;
        while ((aptr[ct] != 0) || (first))
        {
            int cts = 0;
            for (int i = 0; (i < 16) && (aptr[ct] != 0); i++)
            {
                int tmp80_77 = (cts++); char[] tmp80_74 = kptr;tmp80_74[tmp80_77] = ((char)(tmp80_74[tmp80_77] ^ aptr[ct] & 0x7F));
                aptr[ct] = '\000';
                if (ct < aptr.length - 1) {
                    ct++;
                }
            }
            D2des(kptr, kptr);
            first = false;
        }
        useDkey(savek);
    }

    private static void deskey(char[] keyBlock, boolean encrypting, int[] KnL)
    {
        int[] pc1m = new int[56];
        int[] pcr = new int[56];
        int[] kn = new int[32];
        for (int j = 0; j < 56; j++)
        {
            int l = pc1[j];
            int m = l & 0x7;
            pc1m[j] = ((keyBlock[(l >>> 3)] & bytebit[m]) != 0 ? 1 : 0);
        }
        for (int i = 0; i < 16; i++)
        {
            int m;
            if (encrypting) {
                m = i << 1;
            } else {
                m = 15 - i << 1;
            }
            int n = m + 1; int
                tmp118_117 = 0;kn[n] = tmp118_117;kn[m] = tmp118_117;
            for (int j = 0; j < 28; j++)
            {
                int l = j + totrot[i];
                if (l < 28) {
                    pcr[j] = pc1m[l];
                } else {
                    pcr[j] = pc1m[(l - 28)];
                }
            }
            for (int j = 28; j < 56; j++)
            {
                int l = j + totrot[i];
                if (l < 56) {
                    pcr[j] = pc1m[l];
                } else {
                    pcr[j] = pc1m[(l - 28)];
                }
            }
            for (int j = 0; j < 24; j++)
            {
                if (pcr[pc2[j]] != 0) {
                    kn[m] |= bigbyte[j];
                }
                if (pcr[pc2[(j + 24)]] != 0) {
                    kn[n] |= bigbyte[j];
                }
            }
        }
        cookey(kn, KnL);
    }

    private static void des2key(char[] keyBlock, boolean encrypting)
    {
        boolean revmod = encrypting != true;
        char[] rightKey = new char[8];
        char[] lefttKey = new char[8];
        for (int k = 0; k < 8; k++)
        {
            rightKey[k] = keyBlock[(8 + k)];
            lefttKey[k] = keyBlock[k];
        }
        deskey(rightKey, revmod, KnR);

        deskey(lefttKey, encrypting, Kn3);
        for (int i = 0; i < 32; i++) {
            KnL[i] = Kn3[i];
        }
    }

    private static void des(int[] inInts, int[] outInts, int[] keys)
    {
        int keysi = 0;

        int leftt = inInts[0];
        int right = inInts[1];

        int work = (leftt >>> 4 ^ right) & 0xF0F0F0F;
        right ^= work;
        leftt ^= work << 4;

        work = (leftt >>> 16 ^ right) & 0xFFFF;
        right ^= work;
        leftt ^= work << 16;

        work = (right >>> 2 ^ leftt) & 0x33333333;
        leftt ^= work;
        right ^= work << 2;

        work = (right >>> 8 ^ leftt) & 0xFF00FF;
        leftt ^= work;
        right ^= work << 8;
        right = right << 1 | right >>> 31 & 0x1;

        work = (leftt ^ right) & 0xAAAAAAAA;
        leftt ^= work;
        right ^= work;
        leftt = leftt << 1 | leftt >>> 31 & 0x1;
        for (int round = 0; round < 8; round++)
        {
            work = right << 28 | right >>> 4;
            work ^= keys[(keysi++)];
            int fval = SP7[(work & 0x3F)];
            fval |= SP5[(work >>> 8 & 0x3F)];
            fval |= SP3[(work >>> 16 & 0x3F)];
            fval |= SP1[(work >>> 24 & 0x3F)];
            work = right ^ keys[(keysi++)];
            fval |= SP8[(work & 0x3F)];
            fval |= SP6[(work >>> 8 & 0x3F)];
            fval |= SP4[(work >>> 16 & 0x3F)];
            fval |= SP2[(work >>> 24 & 0x3F)];
            leftt ^= fval;
            work = leftt << 28 | leftt >>> 4;
            work ^= keys[(keysi++)];
            fval = SP7[(work & 0x3F)];
            fval |= SP5[(work >>> 8 & 0x3F)];
            fval |= SP3[(work >>> 16 & 0x3F)];
            fval |= SP1[(work >>> 24 & 0x3F)];
            work = leftt ^ keys[(keysi++)];
            fval |= SP8[(work & 0x3F)];
            fval |= SP6[(work >>> 8 & 0x3F)];
            fval |= SP4[(work >>> 16 & 0x3F)];
            fval |= SP2[(work >>> 24 & 0x3F)];
            right ^= fval;
        }
        right = right << 31 | right >>> 1;
        work = (leftt ^ right) & 0xAAAAAAAA;
        leftt ^= work;
        right ^= work;
        leftt = leftt << 31 | leftt >>> 1;
        work = (leftt >>> 8 ^ right) & 0xFF00FF;
        right ^= work;
        leftt ^= work << 8;
        work = (leftt >>> 2 ^ right) & 0x33333333;
        right ^= work;
        leftt ^= work << 2;
        work = (right >>> 16 ^ leftt) & 0xFFFF;
        leftt ^= work;
        right ^= work << 16;
        work = (right >>> 4 ^ leftt) & 0xF0F0F0F;
        leftt ^= work;
        right ^= work << 4;
        outInts[0] = right;
        outInts[1] = leftt;
    }

    private static void D2des(char[] from, char[] into)
    {
        char[] fromR = new char[8];
        char[] fromL = new char[8];
        char[] intoR = new char[8];
        char[] intoL = new char[8];
        for (int i = 0; i < 8; i++)
        {
            fromL[i] = from[i];
            fromR[i] = from[(i + 8)];
        }
        int[] right = new int[2];
        int[] leftt = new int[2];

        scrunch(fromL, leftt);
        scrunch(fromR, right);


        des(leftt, leftt, KnL);
        des(right, right, KnL);

        int swap = leftt[1];
        leftt[1] = right[0];
        right[0] = swap;

        des(leftt, leftt, KnR);
        des(right, right, KnR);
        swap = leftt[1];
        leftt[1] = right[0];
        right[0] = swap;

        des(leftt, leftt, Kn3);
        des(right, right, Kn3);

        unscrunch(leftt, intoL);
        unscrunch(right, intoR);
        for (int i = 0; i < 8; i++)
        {
            into[i] = intoL[i];
            into[(i + 8)] = intoR[i];
        }
    }

    private static byte[] encrypt(byte[] clearText)
    {
        int length = clearText.length;
        if (length % 8 != 0) {
            return null;
        }
        byte[] cipherText = new byte[length];
        int count = length / 8;
        for (int i = 0; i < count; i++) {}
        return cipherText;
    }

    private static byte[] decrypt(byte[] cipherText)
    {
        int length = cipherText.length;
        if (length % 8 != 0) {
            return null;
        }
        byte[] clearText = new byte[length];
        int count = length / 8;
        for (int i = 0; i < count; i++) {}
        return clearText;
    }

    private static final byte[] bytebit = { -128, 64, 32, 16, 8, 4, 2, 1 };
    private static final int[] bigbyte = { 8388608, 4194304, 2097152, 1048576, 524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 };
    private static final char[] Df_Key = { '\001', '#', 'E', 'g', '', '«', 'Í', 'ï', 'þ', 'Ü', 'º', '', 'v', 'T', '2', '\020', '', '«', 'Í', 'ï', '\001', '#', 'E', 'g' };
    private static final int[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
    private static final byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
    private static final byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
    private static final int[] SP1 = { 16843776, 0, 65536, 16843780, 16842756, 66564, 4, 65536, 1024, 16843776, 16843780, 1024, 16778244, 16842756, 16777216, 4, 1028, 16778240, 16778240, 66560, 66560, 16842752, 16842752, 16778244, 65540, 16777220, 16777220, 65540, 0, 1028, 66564, 16777216, 65536, 16843780, 4, 16842752, 16843776, 16777216, 16777216, 1024, 16842756, 65536, 66560, 16777220, 1024, 4, 16778244, 66564, 16843780, 65540, 16842752, 16778244, 16777220, 1028, 66564, 16843776, 1028, 16778240, 16778240, 0, 65540, 66560, 0, 16842756 };
    private static final int[] SP2 = { -2146402272, -2147450880, 32768, 1081376, 1048576, 32, -2146435040, -2147450848, -2147483616, -2146402272, -2146402304, -2147483648, -2147450880, 1048576, 32, -2146435040, 1081344, 1048608, -2147450848, 0, -2147483648, 32768, 1081376, -2146435072, 1048608, -2147483616, 0, 1081344, 32800, -2146402304, -2146435072, 32800, 0, 1081376, -2146435040, 1048576, -2147450848, -2146435072, -2146402304, 32768, -2146435072, -2147450880, 32, -2146402272, 1081376, 32, 32768, -2147483648, 32800, -2146402304, 1048576, -2147483616, 1048608, -2147450848, -2147483616, 1048608, 1081344, 0, -2147450880, 32800, -2147483648, -2146435040, -2146402272, 1081344 };
    private static final int[] SP3 = { 520, 134349312, 0, 134348808, 134218240, 0, 131592, 134218240, 131080, 134217736, 134217736, 131072, 134349320, 131080, 134348800, 520, 134217728, 8, 134349312, 512, 131584, 134348800, 134348808, 131592, 134218248, 131584, 131072, 134218248, 8, 134349320, 512, 134217728, 134349312, 134217728, 131080, 520, 131072, 134349312, 134218240, 0, 512, 131080, 134349320, 134218240, 134217736, 512, 0, 134348808, 134218248, 131072, 134217728, 134349320, 8, 131592, 131584, 134217736, 134348800, 134218248, 520, 134348800, 131592, 8, 134348808, 131584 };
    private static final int[] SP4 = { 8396801, 8321, 8321, 128, 8396928, 8388737, 8388609, 8193, 0, 8396800, 8396800, 8396929, 129, 0, 8388736, 8388609, 1, 8192, 8388608, 8396801, 128, 8388608, 8193, 8320, 8388737, 1, 8320, 8388736, 8192, 8396928, 8396929, 129, 8388736, 8388609, 8396800, 8396929, 129, 0, 0, 8396800, 8320, 8388736, 8388737, 1, 8396801, 8321, 8321, 128, 8396929, 129, 1, 8192, 8388609, 8193, 8396928, 8388737, 8193, 8320, 8388608, 8396801, 128, 8388608, 8192, 8396928 };
    private static final int[] SP5 = { 256, 34078976, 34078720, 1107296512, 524288, 256, 1073741824, 34078720, 1074266368, 524288, 33554688, 1074266368, 1107296512, 1107820544, 524544, 1073741824, 33554432, 1074266112, 1074266112, 0, 1073742080, 1107820800, 1107820800, 33554688, 1107820544, 1073742080, 0, 1107296256, 34078976, 33554432, 1107296256, 524544, 524288, 1107296512, 256, 33554432, 1073741824, 34078720, 1107296512, 1074266368, 33554688, 1073741824, 1107820544, 34078976, 1074266368, 256, 33554432, 1107820544, 1107820800, 524544, 1107296256, 1107820800, 34078720, 0, 1074266112, 1107296256, 524544, 33554688, 1073742080, 524288, 0, 1074266112, 34078976, 1073742080 };
    private static final int[] SP6 = { 536870928, 541065216, 16384, 541081616, 541065216, 16, 541081616, 4194304, 536887296, 4210704, 4194304, 536870928, 4194320, 536887296, 536870912, 16400, 0, 4194320, 536887312, 16384, 4210688, 536887312, 16, 541065232, 541065232, 0, 4210704, 541081600, 16400, 4210688, 541081600, 536870912, 536887296, 16, 541065232, 4210688, 541081616, 4194304, 16400, 536870928, 4194304, 536887296, 536870912, 16400, 536870928, 541081616, 4210688, 541065216, 4210704, 541081600, 0, 541065232, 16, 16384, 541065216, 4210704, 16384, 4194320, 536887312, 0, 541081600, 536870912, 4194320, 536887312 };
    private static final int[] SP7 = { 2097152, 69206018, 67110914, 0, 2048, 67110914, 2099202, 69208064, 69208066, 2097152, 0, 67108866, 2, 67108864, 69206018, 2050, 67110912, 2099202, 2097154, 67110912, 67108866, 69206016, 69208064, 2097154, 69206016, 2048, 2050, 69208066, 2099200, 2, 67108864, 2099200, 67108864, 2099200, 2097152, 67110914, 67110914, 69206018, 69206018, 2, 2097154, 67108864, 67110912, 2097152, 69208064, 2050, 2099202, 69208064, 2050, 67108866, 69208066, 69206016, 2099200, 0, 2, 69208066, 0, 2099202, 69206016, 2048, 67108866, 67110912, 2048, 2097154 };
    private static final int[] SP8 = { 268439616, 4096, 262144, 268701760, 268435456, 268439616, 64, 268435456, 262208, 268697600, 268701760, 266240, 268701696, 266304, 4096, 64, 268697600, 268435520, 268439552, 4160, 266240, 262208, 268697664, 268701696, 4160, 0, 0, 268697664, 268435520, 268439552, 266304, 262144, 266304, 262144, 268701696, 4096, 64, 268697664, 4096, 266304, 268439552, 64, 268435520, 268697600, 268697664, 268435456, 262144, 268439616, 0, 268701760, 262208, 268435520, 268697600, 268439552, 268439616, 0, 268701760, 266240, 266240, 4160, 4160, 262208, 268435456, 268701696 };

    private static void scrunch(char[] inChars, int[] outInts)
    {
        outInts[0] = ((inChars[0] & 0xFF) << '\030');
        outInts[0] |= (inChars[1] & 0xFF) << '\020';
        outInts[0] |= (inChars[2] & 0xFF) << '\b';
        outInts[0] |= inChars[3] & 0xFF;
        outInts[1] = ((inChars[4] & 0xFF) << '\030');
        outInts[1] |= (inChars[5] & 0xFF) << '\020';
        outInts[1] |= (inChars[6] & 0xFF) << '\b';
        outInts[1] |= inChars[7] & 0xFF;
    }

    private static void unscrunch(int[] inInts, char[] outChars)
    {
        outChars[0] = ((char)(inInts[0] >>> 24 & 0xFF));
        outChars[1] = ((char)(inInts[0] >>> 16 & 0xFF));
        outChars[2] = ((char)(inInts[0] >>> 8 & 0xFF));
        outChars[3] = ((char)(inInts[0] & 0xFF));
        outChars[4] = ((char)(inInts[1] >>> 24 & 0xFF));
        outChars[5] = ((char)(inInts[1] >>> 16 & 0xFF));
        outChars[6] = ((char)(inInts[1] >>> 8 & 0xFF));
        outChars[7] = ((char)(inInts[1] & 0xFF));
    }

    private static void cookey(int[] raw, int[] KnL)
    {
        int i = 0;int rawi = 0;
        for (int KnLi = 0; i < 16; i++)
        {
            int raw0 = raw[(rawi++)];
            int raw1 = raw[(rawi++)];
            KnL[KnLi] = ((raw0 & 0xFC0000) << 6);
            KnL[KnLi] |= (raw0 & 0xFC0) << 10;
            KnL[KnLi] |= (raw1 & 0xFC0000) >>> 10;
            KnL[KnLi] |= (raw1 & 0xFC0) >>> 6;
            KnLi++;
            KnL[KnLi] = ((raw0 & 0x3F000) << 12);
            KnL[KnLi] |= (raw0 & 0x3F) << 16;
            KnL[KnLi] |= (raw1 & 0x3F000) >>> 4;
            KnL[KnLi] |= raw1 & 0x3F;
            KnLi++;
        }
    }

    private static void cpkey(int[] into)
    {
        for (int k = 0; k < 32; k++) {
            into[k] = KnL[k];
        }
    }

    private static void cpDkey(int[] into)
    {
        cpkey(into);
        for (int k = 32; k < 64; k++) {
            into[k] = KnR[(k - 32)];
        }
    }

    private static void usekey(int[] from)
    {
        for (int k = 0; k < 32; k++) {
            KnL[k] = from[k];
        }
    }

    private static void useDkey(int[] from)
    {
        usekey(from);
        for (int k = 32; k < 64; k++) {
            KnR[(k - 32)] = from[k];
        }
    }

    public static String hsEncrypt(String paintxt)
            throws Exception
    {
        return hsEncrypt(key.toCharArray(), paintxt.toCharArray());
    }

    public static String hsEncrypt(String key, String paintxt)
            throws Exception
    {
        return hsEncrypt(key.toCharArray(), paintxt.toCharArray());
    }

    public static String hsEncrypt(char[] key, char[] paintxt)
            throws Exception
    {
        char[] pain = new char[33];
        try
        {
            hsEncrypt(key, paintxt, pain);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        StringBuffer results = new StringBuffer();
        int i = 0;
        for (int n = pain.length; i < n; i++)
        {
            char et = pain[i];
            if (et == 0) {
                break;
            }
            results.append(et);
        }
        return results.toString();
    }

    public static String hsDecrypt(String ciphertxt)
            throws Exception
    {
        return hsDecrypt(key.toCharArray(), ciphertxt.toCharArray());
    }

    public static String hsEncryptx(String x,String paintxt) {
//        return hsEncrypt(x.toCharArray(), paintxt.toCharArray());
        return paintxt.toCharArray()+"abc";
    }

    public static String hsDecrypt(String key, String ciphertxt)
            throws Exception
    {
        return hsDecrypt(key.toCharArray(), ciphertxt.toCharArray());
    }

    public static String hsDecrypt(char[] key, char[] ciphertxt)
            throws Exception
    {
        char[] pass = new char[32];
        try
        {
            hsDecrypt(key, ciphertxt, pass);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        StringBuffer results = new StringBuffer();
        int i = 0;
        for (int n = pass.length; i < n; i++)
        {
            char et = pass[i];
            if (et == 0) {
                break;
            }
            results.append(et);
        }
        return results.toString();
    }

    private static void hsEncrypt(char[] key, char[] paintxt, char[] ciphertxt)
            throws Exception
    {
        char[] key2 = new char[16];char[] tmp1 = new char[16];char[] tmp2 = new char[16];
        char[] tmpKey = new char[16];
        if (paintxt.length > 16) {
            throw new Exception("123");
        }
        if (key.length > 15) {
            throw new Exception("456");
        }
        for (int m = 0; m < key.length; m++) {
            tmpKey[m] = key[m];
        }
        make2key(tmpKey, key2);
        des2key(key2, true);
        for (int m = 0; m < paintxt.length; m++) {
            tmp1[m] = paintxt[m];
        }
        D2des(tmp1, tmp2);
        for (int i = 0; i < 16; i++)
        {
            ciphertxt[(i * 2)] = ((char)(tmp2[i] / '\020' + (tmp2[i] / '\020' >= 10 ? 55 : 48)));
            ciphertxt[(i * 2 + 1)] = ((char)(tmp2[i] % '\020' + (tmp2[i] % '\020' >= 10 ? 55 : 48)));
        }
        ciphertxt[32] = '\000';
    }

    private static void hsDecrypt(char[] key, char[] ciphertxt, char[] paintxt)
            throws Exception
    {
        char[] key2 = new char[16];char[] tmp1 = new char[16];char[] tmp2 = new char[16];
        char[] tmpKey = new char[16];
        if (ciphertxt.length > 32) {
            throw new Exception("111");
        }
        if (key.length > 15) {
            throw new Exception("333");
        }
        for (int m = 0; m < key.length; m++) {
            tmpKey[m] = key[m];
        }
        make2key(tmpKey, key2);
        des2key(key2, false);
        for (int i = 0; i < 32; i += 2) {
            tmp1[(i / 2)] = ((char)((ciphertxt[i] - (ciphertxt[i] >= 'A' ? 55 : '0')) * 16 + (ciphertxt[(i + 1)] - (ciphertxt[(i + 1)] >= 'A' ? 55 : '0'))));
        }
        D2des(tmp1, tmp2);
        for (int m = 0; m < 16; m++) {
            paintxt[m] = tmp2[m];
        }
    }

    public static void main(String[] args)
            throws Exception
    {
//        String sPwd = "888888";
//        DESEncrypt e = new DESEncrypt();
//        String str = hsEncrypt(key.toCharArray(), sPwd.toCharArray());
//        System.out.println("str:" + str);
        System.out.println("org:" + hsDecrypt(key.toCharArray(), "F22D36AEBABB49B9BF50DFC65B827297".toCharArray()));
//        System.out.println("888888".toCharArray());
        System.out.println(DESEncrypt.hsEncrypt("999999")+"");
        System.out.println(DESEncrypt.hsEncrypt("99999999")+"");
        System.out.println(DESEncrypt.hsDecrypt("17022886EC00ACB085EF849882490583")+"");
        Scanner sc = new Scanner(System.in);
         System.out.println("请输入你的密文：");
         String name = sc.nextLine();

        String userPwd= DESEncrypt.hsEncrypt(name);
        System.out.println("解密结果==="+userPwd);
    }
}
